#!/usr/bin/env python
# -*- coding: utf-8 -*-

from functools import wraps
from flask import request, jsonify, current_app, g
from flask_jwt_extended import verify_jwt_in_request, get_jwt_identity

from models import User


def rbac_required(resource=None, action=None, roles=None, permissions=None):
    """
    基于RBAC的权限控制装饰器
    
    参数:
        resource (str): 资源名称，如 'user', 'post'
        action (str): 操作名称，如 'create', 'read', 'update', 'delete'
        roles (list): 允许访问的角色列表
        permissions (list): 允许访问的权限列表
    
    用法示例:
        @rbac_required(resource='user', action='create')
        @rbac_required(roles=['admin'])
        @rbac_required(permissions=['user:create'])
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            # 验证JWT令牌
            try:
                verify_jwt_in_request()
                username = get_jwt_identity()
            except Exception as e:
                current_app.logger.error(f"JWT验证失败: {str(e)}")
                return jsonify({
                    'status': 'error',
                    'message': '认证失败，请提供有效的访问令牌',
                    'error': str(e)
                }), 401
            
            # 获取当前用户
            user = User.query.filter_by(username=username).first()
            if not user:
                return jsonify({
                    'status': 'error',
                    'message': '用户不存在'
                }), 404
            
            # 检查用户是否激活
            if not user.is_active:
                return jsonify({
                    'status': 'error',
                    'message': '用户账号已被禁用'
                }), 403
            
            # 将用户对象存储在g对象中，以便在视图函数中使用
            g.current_user = user
            
            # 权限检查逻辑
            has_permission = False
            
            # 管理员角色拥有所有权限
            if user.has_role('admin'):
                has_permission = True
            else:
                # 1. 基于角色的检查
                if roles:
                    for role_name in roles:
                        if user.has_role(role_name):
                            has_permission = True
                            break
                
                # 2. 基于权限的检查
                if permissions and not has_permission:
                    for permission_name in permissions:
                        if user.has_permission(permission_name):
                            has_permission = True
                            break
                
                # 3. 基于资源和操作的检查
                if resource and action and not has_permission:
                    permission_name = f"{resource}:{action}"
                    if user.has_permission(permission_name):
                        has_permission = True
                
                # 如果没有指定任何权限检查条件，则默认允许访问
                if not any([roles, permissions, (resource and action)]):
                    has_permission = True
            
            # 权限验证失败
            if not has_permission:
                return jsonify({
                    'status': 'error',
                    'message': '权限不足，无法访问该资源'
                }), 403
            
            # 权限验证通过，执行原始函数
            return fn(*args, **kwargs)
        return wrapper
    return decorator


def admin_required(fn):
    """
    管理员权限装饰器，要求用户具有admin角色
    """
    return rbac_required(roles=['admin'])(fn)


def permission_required(permission):
    """
    特定权限装饰器，要求用户具有指定权限
    
    参数:
        permission (str): 权限名称，如 'user:create'
    """
    return rbac_required(permissions=[permission])


def role_required(role):
    """
    特定角色装饰器，要求用户具有指定角色
    
    参数:
        role (str): 角色名称，如 'admin', 'editor'
    """
    def decorator(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            # 验证JWT令牌
            try:
                verify_jwt_in_request()
                username = get_jwt_identity()
            except Exception as e:
                current_app.logger.error(f"JWT验证失败: {str(e)}")
                return jsonify({
                    'status': 'error',
                    'message': '认证失败，请提供有效的访问令牌',
                    'error': str(e)
                }), 401
            
            # 获取当前用户
            user = User.query.filter_by(username=username).first()
            if not user:
                return jsonify({
                    'status': 'error',
                    'message': '用户不存在'
                }), 404
            
            # 检查用户是否激活
            if not user.is_active:
                return jsonify({
                    'status': 'error',
                    'message': '用户账号已被禁用'
                }), 403
            
            # 将用户对象存储在g对象中，以便在视图函数中使用
            g.current_user = user
            
            # 检查用户是否有指定角色或管理员角色
            if user.has_role(role) or user.has_role('admin'):
                return fn(*args, **kwargs)
            
            # 权限验证失败
            return jsonify({
                'status': 'error',
                'message': '权限不足，无法访问该资源'
            }), 403
        return wrapper
    return decorator


def resource_action_required(resource, action):
    """
    资源操作装饰器，要求用户具有对指定资源的指定操作权限
    
    参数:
        resource (str): 资源名称，如 'user', 'post'
        action (str): 操作名称，如 'create', 'read', 'update', 'delete'
    """
    return rbac_required(resource=resource, action=action)